home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / msdos / raytrace / pov / gen / pvcoil21 / coil.cpp < prev    next >
C/C++ Source or Header  |  1993-09-17  |  19KB  |  488 lines

  1. /* 
  2.  Program : Coil v2.0  
  3.  Purpose : Create coil objects for PoV Ray v1.0 raytracer
  4.  Created : 7/25/92
  5.  By      : Bill Kirby CIS [70711,2407]
  6.  File    : COIL.C
  7.  Compiler: Borland C++ v3.1
  8.  Model   : Small
  9.  Comments: Creates twisted coil object made with spheres.
  10. */ 
  11. /*         
  12.  Program : Coil v2.10b 
  13.  Purpose : Create coil objects for PoV Ray v1.0 and Polyray v1.6 raytracers
  14.            and also export to CTDS and WORM file formats.   
  15.  Created : 9/14/93
  16.  By      : Rob Bryerton CIS [73747,433]... based on original C code 
  17.            by Bill Kirby
  18.  File    : COIL.CPP
  19.  Compiler: Microsoft C++ v8.00  
  20.  Model   : Small
  21.  Comments: Creates twisted coil object made with spheres or other shapes
  22. */ 
  23.  
  24. #include <fstream.h>
  25. #include <math.h>    
  26. #include <stdio.h>  // for getchar()
  27. #include <stdlib.h>  
  28. #include <string.h>
  29. #include <graph.h>   // for graphics
  30.  
  31. ofstream outfile;   
  32. const int BUFFSIZE = 256;
  33. enum Format {POV,POLY,CTDS,WORM}; 
  34. enum bool   {FALSE,TRUE};
  35. enum Shape  {Sphere,Ellipsoid,Box,Cone,Y_Cylinder};
  36. char buff[BUFFSIZE];
  37. const double PI = 3.1415926535897932384626;
  38.  
  39. /*
  40. #ifndef PI
  41. #define PI 3.1415926535897932384626
  42. #endif*/
  43.  
  44.  
  45. void err_exit(char *message);
  46. void usage(void);
  47.  
  48. class Base_Obj
  49. {
  50.    protected:                             
  51.     double x_1,y_1,x_2,z_2,xpos,ypos,zpos,Rad1,rad2,radius,angle1,angle2,k;    
  52.     double xpos_1,ypos_1;  // for graphics... remembers 1st graphics points
  53.     long Ntwist,Ntube,counter,steps,shape_type;
  54.     char com[3],union_name[80];
  55.     bool extended, display;
  56.     Format format;
  57.     Shape shape;
  58.     int v_mode;
  59.    public:                             
  60.     char filename[80];                      
  61.     Base_Obj(){         //  no arg constructor          
  62.         xpos=0.0; ypos=0.0; zpos=0.0; radius=0.25;strcpy(com,"//");
  63.         extended=FALSE;display = FALSE; format=POV; counter=0;shape=Sphere;
  64.         outfile.setf(ios::showpoint | ios::fixed);outfile.precision(6);  }       
  65.     virtual void do_calc(void);
  66.     virtual void get_inputs(void); 
  67.     void init_display(void);
  68.     void close_display(void);
  69.     void draw_piece(void);
  70.     void process_args(int argc, char* argv[]);  
  71.     void process_option(char *s);   
  72.     void set_precision(char *prec);     
  73.     void show_title(void);
  74.     virtual void write_end(void){};   
  75.     virtual void write_header(void);
  76.     virtual bool write_piece(void){if(display) draw_piece();  // draw current line
  77.                                    return (counter < steps) ? TRUE:FALSE; }    
  78. }; 
  79.  
  80. class POV_Obj:public Base_Obj
  81. {   
  82.    private:    
  83.     double xmax,xmin,ymax,ymin,zmax,zmin;     
  84.    public:
  85.     POV_Obj(){
  86.         xmax=0.0,xmin=0.0,ymax=0.0, // no arg constructor 
  87.         ymin=0.0,zmax=0.0,zmin=0.0;}      
  88.     void do_calc(void);    
  89.     void get_inputs(void);      
  90.     void write_header(void);    
  91.     bool write_piece(void);
  92.     void write_end(void);
  93. };
  94.  
  95. class POLY_Obj:public Base_Obj
  96. {   
  97.    public: 
  98.     POLY_Obj(){format=POLY;}
  99.     void get_inputs(void);          
  100.     void write_header(void);
  101.     bool write_piece(void);
  102.     void write_end(void);       
  103. };               
  104.  
  105. class CTDS_Obj:public Base_Obj  // ********** full definition of class
  106. {
  107.    public:
  108.     CTDS_Obj() {format=CTDS; strcpy(com,";"); strcpy(union_name,"-----");}
  109.     bool write_piece(void) 
  110.         {
  111.         outfile << xpos << " " << ypos << " " << zpos << " " 
  112.                 << radius << endl;
  113.         Base_Obj::write_piece();  
  114.         return ((counter < steps) ? TRUE:FALSE);
  115.         }                 
  116.     void write_end(void){};
  117. };              
  118.  
  119. class WORM_Obj:public Base_Obj  // ********** full definition of class
  120. {
  121.    public:
  122.     WORM_Obj(){format=WORM;}
  123.     void write_header(void)
  124.         { outfile << steps << endl; }
  125.     bool write_piece(void) 
  126.         {
  127.         outfile << xpos << ", " << ypos << ", " << zpos << ", " 
  128.                 << radius <<", " << (counter==1?0:1) << endl;  
  129.        Base_Obj::write_piece(); 
  130.         return ((counter < steps) ? TRUE:FALSE);}
  131.     void write_end(void){};    
  132. };              
  133.  
  134.  
  135.  
  136. //main
  137. int main(int argc, char* argv[])
  138. {   
  139.     int choice = 1;
  140.     
  141.     Base_Obj* coil_ptr;    // pointer to class Base_Obj
  142.     Base_Obj vec;          // object of   " "   "  "
  143.     coil_ptr = &vec;
  144.         
  145.     if(argc > 1) coil_ptr->process_args (argc, argv); // check for validity
  146.         
  147.     coil_ptr->show_title();
  148.                      
  149.     cout<< "1\tPOV\n2\tPolyray\n3\tCTDS\n4\tWORM\n" << "Number for format? [1]: ";
  150.     cin.getline(buff,BUFFSIZE); choice = atoi(buff); // output format   
  151.     
  152.     switch(choice){ // construct appropriate object based on above choice   
  153.         case 2: {POLY_Obj vec2; coil_ptr = &vec2;} break;
  154.         case 3: {CTDS_Obj vec3; coil_ptr = &vec3;} break; 
  155.         case 4: {WORM_Obj vec4; coil_ptr = &vec4;} break;                                  
  156.         default:{POV_Obj  vec1; coil_ptr = &vec1;}  }
  157.                 
  158.     if(argc > 1) coil_ptr->process_args (argc, argv);    // set options      
  159.     
  160.     coil_ptr->get_inputs();         //   get parameters from user
  161.     
  162.     outfile.open(coil_ptr->filename,ios::out);      // try to open disk file
  163.     if(! outfile)   err_exit("Opening file.");   // if disk access error,exit       
  164.         
  165.     coil_ptr->write_header();       //  success, make a coil  
  166.     
  167.     coil_ptr->init_display();     // set up display if desired
  168.     cerr<< "\nCreating data file " << coil_ptr->filename << endl;
  169.     
  170.     do coil_ptr->do_calc();         //  calculate current vector        
  171.     while(coil_ptr->write_piece()); //  write current line to disk
  172.     
  173.     coil_ptr->write_end();  //  write texture block (POV or Polyray only)
  174.     outfile.close;          //  close disk file  
  175.     
  176.     coil_ptr->close_display();  // exit graphics mode if applicable         
  177.     cout << "\nFile " << coil_ptr->filename <<" created.\n";       
  178.     
  179.     return(0);
  180. }    
  181.  
  182.  
  183.  
  184. void err_exit(char *message)
  185. {                    
  186.     cerr << "\n\nERROR! \a" << message << "... Exiting \n"; 
  187.     exit(1);
  188. }       
  189.  
  190.  
  191. void usage()
  192. {
  193.     cerr << "\n--------------------------------Coil v2.10--------------------------------------"    
  194.         << "Usage: coil [options]\n"
  195.         << "Options:  -d#   enables 2D (xy) display of coil... # is the graphics mode\n"
  196.         << "                1=640x480  2=800x600  3=1024x768  (default # value is 1)\n\n"
  197.         << "          -e    gives you an extended menu with a choice of objects \n"
  198.         << "                (cone, cylinder, box, etc.) for POV-Ray or Polyray output.\n\n"
  199.         << "          -p#   where # is the precision of the output file numbers.\n"
  200.         << "                Range is 2 - 9 with a default precision of 6 decimal places.\n" 
  201.         << "\nType COIL with no parameters for the default menus and options.\n"
  202.         <<    "--------------------------------------------------------------------------------";
  203. }       
  204.  
  205.  
  206.  
  207. // ************* Base and Derived Class function definitions**************
  208.  
  209.  
  210. //   ************* Base Class Base_Obj function definitions **************
  211.  
  212. void Base_Obj::close_display()
  213.     if(display){
  214.       cerr << "\nPress return."; 
  215.       getchar(); 
  216.       _setvideomode(_DEFAULTMODE);}
  217. }      
  218.  
  219. void Base_Obj::do_calc()
  220.     angle1 = 2 * PI * Ntube * (double)counter / (double)steps;      
  221.     x_1 = cos( angle1 );y_1 = sin( angle1 );        
  222.     angle2 = (double)( Ntwist + 1.0/Ntube) * angle1;      
  223.     x_2 = cos( angle2 );z_2 = sin( angle2);     
  224.     xpos = k * ((Rad1 * x_1) + (rad2 * x_2 * x_1));
  225.     ypos = k * ((Rad1 * y_1) + (rad2 * x_2 * y_1));
  226.     zpos = k * rad2 * z_2; counter++;      
  227. }   
  228.  
  229. void Base_Obj::draw_piece()
  230.     struct _videoconfig vc;
  231.     _getvideoconfig( &vc );
  232.     _setcolor (12); /* brt red */ 
  233.     double rads = Rad1+rad2;      
  234.     int vidx = int((xpos*(vc.numxpixels*0.33)/k)/rads+(0.5*vc.numxpixels));
  235.     int vidy = int((ypos*(vc.numxpixels*0.33)/k)/rads+(0.5*vc.numypixels));    
  236.     if(counter==1){ _moveto (vidx, vidy); xpos_1=vidx; ypos_1=vidy; }              
  237.     if(counter<=steps){ _lineto (vidx,vidy); _setcolor (10); /* brt grn */
  238.        int elip_x1 = (vidx-(radius*(0.28*vc.numypixels/k)));
  239.        int elip_y1 = (vidy-(radius*(0.28*vc.numypixels/k)));
  240.        int elip_x2 = (vidx+(radius*(0.28*vc.numypixels/k))); 
  241.        int elip_y2 = (vidy+(radius*(0.28*vc.numypixels/k)));
  242.         //_ellipse( _GBORDER, vidx-(radius*(0.28*vc.numxpixels)),vidy-(radius*(0.28*vc.numxpixels)),vidx+(radius*(0.28*vc.numxpixels)),vidy+(radius*(0.28*vc.numxpixels))); }
  243.         _ellipse( _GBORDER, elip_x1, elip_y1, elip_x2, elip_y2); }
  244.     if(counter==steps){ _setcolor (12);  _lineto (xpos_1,ypos_1);      }
  245. }      
  246.     
  247.  
  248.  
  249. void Base_Obj::get_inputs() 
  250. {           
  251.     cout << "Ouput filename? [coil.inc]: ";
  252.     cin.getline(buff,BUFFSIZE);     strcpy(filename,buff); 
  253.     
  254.     if(format < CTDS){
  255.       cout << "Union name? [coil]: ";
  256.       cin.getline(buff,BUFFSIZE);     strcpy(union_name,buff);}                  
  257.             
  258.     cout << "Number of objects? [100]: ";
  259.     cin.getline(buff,BUFFSIZE);     steps = atoi(buff);
  260.             
  261.     cout << "Number of objects in cross-section? [2]: ";
  262.     cin.getline(buff,BUFFSIZE);     Ntube = atoi(buff);
  263.  
  264.     cout << "Number of twists per revolution? [2]: ";
  265.     cin.getline(buff,BUFFSIZE);     Ntwist = atoi(buff);
  266.  
  267.     cout << "Major radius? [1.0]: ";
  268.     cin.getline(buff,BUFFSIZE);     Rad1 = atof(buff);
  269.  
  270.     cout << "Minor radius? [0.25]: ";
  271.     cin.getline(buff,BUFFSIZE);     rad2 = atof(buff);
  272.  
  273.     cout << "Object 'radius'? [0.25]: ";
  274.     cin.getline(buff,BUFFSIZE);     radius = atof(buff);
  275.  
  276.     cout << "Overall scale value (k)? [1.0]: ";
  277.     cin.getline(buff,BUFFSIZE);     k = atof(buff);
  278.  
  279.     // Set up default values      
  280.     if(filename[0]=='\0') strcpy(filename,"coil.inc");
  281.     if(union_name[0]=='\0') strcpy(union_name,"coil");
  282.     if(steps==0) steps = 100;   if(Ntube==0) Ntube = 2;
  283.     if(Ntwist==0) Ntwist = 2;   if(Rad1==0.0) Rad1 = 1.0;
  284.     if(rad2==0.0) rad2 = 0.25;  if(radius==0.0) radius = 0.25;
  285.     if(k==0.0) k = 1.0;         if(shape_type==0) shape_type = 1;
  286.         switch(shape_type){
  287.             case 2 :    shape = Ellipsoid;  break;
  288.             case 3 :    shape = Box;        break;
  289.             case 4 :    shape = Cone;       break;
  290.             case 5 :    shape = Y_Cylinder; break;
  291.             default:    shape = Sphere; 
  292.         }
  293. }
  294.  
  295. void Base_Obj::init_display() 
  296. {  if(display){
  297.     switch(v_mode){
  298.         case 3  : if(!_setvideomode(_XRES16COLOR)) cerr << "\nCouldn't set graphics mode... continuing\n";
  299.                 break;  /* 1024x768x16 */
  300.         case 2  : if(!_setvideomode(_SRES16COLOR)) cerr << "\nCouldn't set graphics mode... continuing\n";
  301.                 break;  /*  800x600x16 */
  302.         default : if(!_setvideomode(_VRES16COLOR)) cerr << "\nCouldn't set graphics mode... continuing\n";
  303.      }                  /*  640x480x16 */
  304.    }
  305. }
  306.  
  307. void Base_Obj::process_args (int argc, char* argv[])
  308. {
  309.     for (int i = 1; i < argc; i++)
  310.     {
  311.         if (argv[i][0] == '-' || argv[i][0] == '/')
  312.             process_option (&argv[i][1]);
  313.         else
  314.         {usage();   err_exit("Invalid option");}
  315.     }
  316. }     
  317.  
  318.  
  319. void Base_Obj::process_option (char *s)
  320. {
  321.     switch (toupper(s[0]))
  322.     {
  323.     case 'E': extended = TRUE; break;
  324.     case 'P': set_precision(&s[1]);  break;
  325.     case 'D': display = TRUE; v_mode = atoi(&s[1]); break;      
  326.     case '?': usage(); exit(0);
  327.     case 'H': usage(); exit(0);
  328.     default : usage();  err_exit("Invalid option");     
  329.     }
  330. }
  331.  
  332.  
  333. void Base_Obj::set_precision(char *prec)
  334. {  
  335.     outfile.precision((atoi(prec) > 1 ? atoi(prec) : 6 ));  
  336. }
  337.  
  338.  
  339. void Base_Obj::show_title()
  340. {   
  341.     cout << "Coil v2.10\n"    
  342.         << "Creates a data file of a twisted coil object for the PoV-Ray v1.0" << endl
  343.         << "and Polyray v1.6 raytracers, Connect The Dots Smoother (CTDS), and WORM.\n"    
  344.         << "- v2.0 C source by W. D. Kirby 7/25/92\n"   
  345.         << "- v2.1 C++ update by R. Bryerton  9/14/93\n\n"; 
  346. }                 
  347.  
  348.  
  349.  
  350. void Base_Obj::write_header()
  351. {  
  352.     outfile 
  353.     <<com<<" File: "<<filename<<"  Union Name: "<<union_name<< endl
  354.     <<com<<" This data file created by COIL.EXE v2.10 for the PoV Ray v1.0 and\n"
  355.     <<com<<" Polyray v1.6 raytracers, Connect The Dots Smoother (CTDS), and WORM.\n\n"  
  356.     <<com<<"  Twists="<<Ntwist<<"  Cross Section="<<Ntube<<"  Objects="<<steps<<"  Scale=" << k << "\n\n";
  357. }
  358.  
  359.  
  360. // *************************** Derived Class POV_Obj function definitions
  361. void POV_Obj::get_inputs()
  362. {   
  363.     if(extended){
  364.     cout << "\n1\tSphere\n2\tEllipsoid\n3\tBox\n4\tCone\n5\tY_Cylinder\n";  
  365.     cout << "Shape type? [1]: ";
  366.     cin.getline(buff,BUFFSIZE);     shape_type = atoi(buff); }
  367.         
  368.     Base_Obj::get_inputs();     //  call base class function
  369. }
  370.  
  371. void POV_Obj::do_calc() 
  372. {                      
  373.     Base_Obj::do_calc();            //call base class function 1st
  374.     xmax = __max(xmax,xpos);xmin = __min(xmin,xpos); // calculate bounds  
  375.     ymax = __max(ymax,ypos);ymin = __min(ymin,ypos); //  (POV only)
  376.     zmax = __max(zmax,zpos);zmin = __min(zmin,zpos);
  377. }       
  378.  
  379. void POV_Obj::write_header()
  380. {
  381.     Base_Obj::write_header();   //  call base class function first
  382.     
  383.     if(shape > Sphere){ 
  384.     outfile << "//   You MUST #declare shapes.inc in either this file or your .POV file...\n\n"
  385.             << "#declare object_scale = <" << 0.5*radius << " "<< 0.5*radius << " "<< 0.5*radius << ">"<< endl
  386.             << "#declare object_rotate = <0 0 0>" << endl
  387.             << "//   Change object_scale and object_rotate to modify EVERY object\n\n";
  388.     }
  389.     
  390.     outfile << "declare "<<union_name<<" = object {\n union {\n";
  391.                 
  392. }   
  393.  
  394.  
  395. bool POV_Obj::write_piece() 
  396. {
  397.     switch(shape){
  398.     case Ellipsoid  : outfile << "      quadric { Ellipsoid scale object_scale rotate object_rotate translate< "<<xpos<<" "<<ypos<<" "<<zpos<<" > } \n";    break;
  399.     case Box        : outfile << "      box { UnitBox scale object_scale rotate object_rotate translate< "<<xpos<<" "<<ypos<<" "<<zpos<<" > } \n";  break;
  400.     case Cone       : outfile << "      intersection { Cone_Y scale object_scale rotate object_rotate translate< "<<xpos<<" "<<ypos<<" "<<zpos<<" > } \n";  break;
  401.     case Y_Cylinder : outfile << "      intersection { Disk_Y scale object_scale rotate object_rotate translate< "<<xpos<<" "<<ypos<<" "<<zpos<<" > } \n";  break;
  402.     default         : outfile << "      sphere { < "<<xpos<<" "<<ypos<<" "<<zpos<<" > "<<radius<<" }\n";}
  403.     Base_Obj::write_piece(); return (counter < steps) ? TRUE:FALSE; 
  404. }
  405.  
  406. void POV_Obj::write_end() 
  407. {                           // calculate bounding box
  408.     xmax = 1.01 * (xmax + radius); xmin = 1.01 * (xmin - radius);
  409.     ymax = 1.01 * (ymax + radius); ymin = 1.01 * (ymin - radius);
  410.     zmax = 1.01 * (zmax + radius); zmin = 1.01 * (zmin - radius);     
  411.     outfile << " }\n\n" 
  412.             << "bounded_by {\n"
  413.             << "  box { < " << xmin<<" "<<ymin<<" "<<zmin << "> < "
  414.                             << xmax<<" "<<ymax<<" "<<zmax << "> }\n }\n"
  415.             << "  texture {\n"
  416.             << "    ambient 0.3\n"
  417.             << "    diffuse 0.7\n"
  418.             << "    phong 1.0\n"
  419.             << "    phong_size 20.0\n"
  420.             << "    color red 1.0 green 0.0 blue 0.0\n"   
  421.             << "  }\n\n}\n\n";  
  422.   
  423. }  
  424.                      
  425. // *************************** Derived Class POLY_Obj function definitions
  426. void POLY_Obj::get_inputs()
  427. {   
  428.     if(extended){
  429.     cout << "\n1\tSphere\n2\tEllipsoid\n3\tBox\n4\tCone\n5\tY_Cylinder\n\n";    
  430.     cout << "Shape type? [1]: ";
  431.     cin.getline(buff,BUFFSIZE);     shape_type = atoi(buff);}
  432.         
  433.     Base_Obj::get_inputs(); //  call base class function
  434. }           
  435.  
  436. void POLY_Obj::write_header()
  437. {
  438.     Base_Obj::write_header();   //  call base class function first
  439.     
  440.     if(shape > Sphere) outfile  << "define object_scale <" << 0.5*radius << ", " << 0.5*radius << ", " << 0.5*radius << ">\n"
  441.                                 << "define object_rotate <0, 0, 0>\n"
  442.                                 <<"//   Change object_scale and object_rotate to modify EVERY object\n\n";
  443.                                 
  444.     switch(shape){     // cap the cone and cylinder to be consistent w/POV
  445.     case Ellipsoid : outfile << "define Ellipsoid object{ sphere<0,0,0>,1 scale object_scale rotate object_rotate}\n"; break;   
  446.     case Box       : outfile << "define UnitBox object{ box<-1,-1,-1>,<1,1,1> scale object_scale rotate object_rotate}\n";break;
  447.     case Cone      : outfile << "define Y_Cone  object{\n  object{cone<0,-1,0>,1,<0,1,0>,0  scale object_scale rotate object_rotate}+\n"
  448.                              << "  object {disc <0, -1, 0>, <0, 1, 0>, 1 scale object_scale rotate object_rotate}\n}\n";break;
  449.     case Y_Cylinder: outfile << "define Y_Cylinder object{\n  object{cylinder<0,-1,0>,<0,1,0>,1 scale object_scale rotate object_rotate}+\n"
  450.                              << "  object {disc <0, 1, 0>, <0, 1, 0>, 1 scale object_scale rotate object_rotate}+\n"
  451.                              << "  object {disc <0, -1, 0>, <0, 1, 0>, 1 scale object_scale rotate object_rotate}\n}\n";break;
  452.     default :  break;   }
  453.     outfile << "\ndefine "<<union_name<<"\n  object {\n";
  454. }   
  455.  
  456. bool POLY_Obj::write_piece() 
  457. {    
  458.     switch(shape){
  459.     case Ellipsoid : outfile << "     Ellipsoid{ translate<" << xpos << ", " << ypos << ", " << zpos << ">} "; break;
  460.     case Box       : outfile << "     UnitBox{ translate<" << xpos << ", " << ypos << ", " << zpos << ">} "; break;
  461.     case Cone      : outfile << "     Y_Cone{ translate<" << xpos << ", " << ypos << ", " << zpos << ">} "; break;
  462.     case Y_Cylinder: outfile << "     Y_Cylinder{ translate<" << xpos << ", " << ypos << ", " << zpos << ">} "; break;
  463.     default        : outfile << "     object { sphere < "<<xpos<<", "<<ypos<<", "<<zpos<<" >, "<<radius<<" } ";}
  464.  
  465.     if (counter < steps)  // for all obects EXCEPT the last 
  466.         outfile << "+\n";
  467.     else                 // for last object only (no "+")
  468.         outfile << endl;   
  469.                 
  470.     Base_Obj::write_piece(); return (counter < steps) ? TRUE:FALSE;
  471. }
  472.  
  473. void POLY_Obj::write_end()
  474. {
  475.     outfile << "  texture {\n"
  476.             << "    surface {\n"
  477.             << "      ambient red, 0.275\n"      
  478.             << "      diffuse red, 0.8\n"        
  479.             << "      specular white, 1.0\n"
  480.             << "      microfacet Phong 7\n     }\n"
  481.             << "  }\n\n}\n\n";                            
  482.         
  483.  
  484.